package com.jindy.file.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.jindy.file.config.OssProperties;
import com.jindy.file.domain.FileUploadEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author yqq
 * @date 2023/3/24
 * @Description 文件工具类
 */
@Component
public class FileUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);

    /**
     * oss 配置类
     */
    @Resource
    private OssProperties ossProperties;

    /**
     * 文件上传
     * @param uploadFile
     * @return
     */
    public FileUploadEntity upload(MultipartFile uploadFile) {
        /**
         * 获取oss的属性
         */
        String endpoint = ossProperties.getEndpoint();
        String accessKeyId = ossProperties.getKeyId();
        String accessKeySecret = ossProperties.getKeySecret();
        String bucketName = ossProperties.getBucketName();
        String fileHost = ossProperties.getFileHost();

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);


        Map<String, String> map = new HashMap<>();

        // 获取文件原名称
        String originalFilename = uploadFile.getOriginalFilename();
        // 获取文件类型
        String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 新文件名称
        String newFileName = UUID.randomUUID() + fileType;
        // 构建日期路径, 例如：OSS目标文件夹/2020/10/31/文件名
        String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 文件上传的路径地址
        String uploadImgeUrl = fileHost + "/" + filePath + "/" + newFileName;
        String url ="";
        try {
            // 获取文件输入流
            InputStream inputStream = uploadFile.getInputStream();
            //文件上传至阿里云OSS
            ossClient.putObject(bucketName, uploadImgeUrl, inputStream);
            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
            url=ossClient.generatePresignedUrl(bucketName, uploadImgeUrl,expiration).toString();
            LOGGER.info("上传文件地址："+url);
        } catch (Exception e) {
            LOGGER.error("文件上传失败",e);
            throw new RuntimeException("文件上传失败",e);
        }

        /**
         * 注意：在实际项目中，文件上传成功后，数据库中存储文件地址
         */
        // 获取文件上传后的图片返回地址
        // String returnImgeUrl = "http://" + bucketName + "." + endpoint + "/" + uploadImgeUrl;
        FileUploadEntity entity = new FileUploadEntity();
        entity.setFileType(fileType);
        entity.setServerFileName(newFileName);
        entity.setName(originalFilename);
        entity.setVisitUrl(url);
        entity.setFilePath(filePath);
        entity.setSize(uploadFile.getSize());
        return entity;
    }

    /**
     * 文件下载
     * @param fileName
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    public void download(String fileName, String filePath, HttpServletResponse response) throws UnsupportedEncodingException {
        // 文件名以附件的形式下载
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        String endpoint = ossProperties.getEndpoint();
        String accessKeyId = ossProperties.getKeyId();
        String accessKeySecret = ossProperties.getKeySecret();
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 获取oss的Bucket名称
        String bucketName = ossProperties.getBucketName();
        // 获取oss目标文件夹
        String filehost = ossProperties.getFileHost();
        // 日期目录
        // 注意，这里虽然写成这种固定获取日期目录的形式，逻辑上确实存在问题，但是实际上，filePath的日期目录应该是从数据库查询的
        // String filePath = new DateTime().toString("yyyy/MM/dd");

        String fileKey = filehost + "/" + filePath + "/" + fileName;
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, fileKey);
        try {
            // 读取文件内容。
            InputStream inputStream = ossObject.getObjectContent();
            // 把输入流放入缓存流
            BufferedInputStream in = new BufferedInputStream(inputStream);
            ServletOutputStream outputStream = response.getOutputStream();
            // 把输出流放入缓存流
            BufferedOutputStream out = new BufferedOutputStream(outputStream);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            if (out != null) {
                out.flush();
                out.close();
            }
            if (in != null) {
                in.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
